; This module initializes the microcontroller then executes MAIN forever
;
Reset:
MOV SP, #235 ; Initialize the Stack at top of internal memory
MOV PageReg, #7FH ; Needed to use MOVX @Ri
MOV R0, #LOW(USBControl) ; Simulate a disconnect
MOVX A, @R0
ANL A, #11110011b ; Clear DISCON, DISCOE
MOVX @R0, A
CALL Wait100msec ; Give the host time to react
MOVX A, @R0 ; Reconnect with this new identity
ORL A, #00000110b ; Set DISCOE to enable pullup resistor
MOVX @R0, A ; Set RENUM so that 8051 handles USB requests
CLR A
MOV FLAGS, A ; Start in Default state
InitializeIOSystem: ; This example uses only I2C signals
; No initialization is required
InitializeInterruptSystem: ; First initialize the USB level
MOV R0, #LOW(IN07IEN)
MOVX @R0, A ; Disable interrupts from IN Endpoints 0-7
INC R0
MOVX @R0, A ; Disable interrupts from OUT Endpoints 0-7
INC R0
MOV A, #00000011b
MOVX @R0, A ; Enable (Resume, Suspend,) SOF and SUDAV INTs
INC R0
MOV A, #00000001b
MOVX @R0, A ; Enable Auto Vectoring for USB interrupts
MOV R0, #LOW(OUT07IRQ)
MOV A, #0FFH
MOVX @R0, A ; Clear out any pending interrupts
; Now enable the main level
MOV EIE, #00000001b ; Enable INT2 = USB Interrupt (only)
MOV EI, #11000000b ; Enable interrupt subsystem (and Ser1 for Dscope)
; Initialization Complete.
;
MAIN:
NOP ; Not much of a main loop for this example
JMP MAIN ; All actions are initiated by interrupts
; We are a slave, we wait to be told what to do
Wait100msec:
MOV Temp, #100
Wait1msec: ; A delay loop
MOV DPTR, #-1200
More: INC DPTR ; 3 cycles
MOV A, DPL ; + 2
ORL A, DPH ; + 2
JNZ More ; + 3 = 10 cycles x 1200 = 1msec
DJNZ Temp, Wait1msec
RET
Wait4Stop: ; Make sure the STOP from a previous
MOVX A, @R0 ; I2C transaction has completed
JB ACC.6, Wait4Stop
RET
SendI2Caddress: ; Send the first byte to I2C bus
CALL Wait4Stop
MOV A, #10000000b ; Set the START bit
MOVX @R0, A ; I2C engine now primed
SendI2Cdatabyte:
MOVX A, @DPTR ; Get data and . . .
MOVX @R1, A ; . . . send using I2C engine
Wait4Done:
MOVX A, @R0
JNB ACC.0, Wait4Done ; Wait for the data to be transmitted
RET
ProcessOutputReport: ; A Report has just been received
; The report is two bytes long
; Byte 1, Bits[7:1] = an I2C Address, Bit[0] = direction (0 = Write)
; Byte 2 = DataByte if byte 1 specifies a write
MOV R0, #LOW(I2CControl) ; Initialize the pointers to be used
MOV R1, #LOW(I2CData)
MOV DPTR, #EP0OutBuffer ; Point to the Report
CALL SendI2Caddress
MOVX A, @DPTR ; Retrieve Report Byte 1
JB ACC.0, I2C_Read
I2C_Write:
INC DPTR ; Point to data byte to write
CALL SendI2Cdatabyte
MOV A, #01000000b ; Set the STOP bit
MOVX @R0, A
RET
I2C_Read:
MOV A, #00100000b ; Set the LASTRD bit
MOVX @R0, A
MOVX A, @R1 ; Dummy read of I2C_Data
CALL Wait4Done
MOV A, #01000000b ; Set the STOP bit
MOVX @R0, A ; Immediately follow with . . .
MOVX A, @R1 ; . . . read the I2C bus data
; Fall into CreateInputReport
CreateInputReport:
; The report is only one byte long in this example
; It contains the byte read from the I2C bus
MOV DPTR, #EP1InBuffer ; Point to the buffer
MOVX @DPTR, A ; Update the Report
MOV DPTR, #IN1ByteCount
MOV A, #1
MOVX @DPTR, A ; Endpoint 1 now 'armed', next IN will get data
RET